//
//  instrument_view.m
//  sbrush
//
//  Created by Phillip Popp on 4/30/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "instrument_view.h"
#include <vector>

using namespace sbrush;
using namespace std;

#define INIT_BUFFER_SIZE (100)

@implementation InstrumentView

- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
		[self setAutoresizesSubviews:YES];
		[self setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
		_stateBuffer1 = new vector<InstrumentState*>();
		_stateBuffer2 = new vector<InstrumentState*>();
		_drawBuffer = _stateBuffer1;
		_loadBuffer = _stateBuffer2;
		_returnBuffer = new vector<const InstrumentState*>();
		_drawBufferSize = 0;
		_loadBufferSize = 0;
		
		_bufferSwapLock = [[NSLock alloc] init];
		
		/* initialize buffers with memory to lesson amount of mallocing during 
		 * runtime */
		while (_stateBuffer1->size() < INIT_BUFFER_SIZE) {
			_stateBuffer1->push_back(new InstrumentState());
		}
		while (_stateBuffer2->size() < INIT_BUFFER_SIZE) {
			_stateBuffer2->push_back(new InstrumentState());
		}
    }
    return self;
}

- (void) dealloc {
	
	for (size_t i = 0; i < _stateBuffer1->size(); i++) {
		delete _stateBuffer1->at(i);
	}
	for (size_t i = 0; i < _stateBuffer2->size(); i++) {
		delete _stateBuffer2->at(i);
	}
	delete _stateBuffer1;
	delete _stateBuffer2;
	delete _returnBuffer;
	[_bufferSwapLock release];

	[super dealloc];
}


- (BOOL) acceptsFirstResponder {
	return YES;
}

- (BOOL)becomeFirstResponder {
	return YES;
}
- (void)viewDidMoveToWindow {
	[self setFrame:[[self superview] bounds]];
	[self needsDisplay];
}

- (void)viewWillMoveToWindow:(NSWindow *)newWindow {
	[[self window] setAcceptsMouseMovedEvents:NO];
}
- (void) clear {
}

- (void) update:(const InstrumentState*)state {
	/* TODO: what happens to these locks if an obj-c exception is throw? */
	[_bufferSwapLock lock];
	try {
		if (_loadBuffer->size() < (_loadBufferSize + 1)) {
			_loadBuffer->push_back(new InstrumentState());
		}
		*_loadBuffer->at(_loadBufferSize) = *state;
		_loadBufferSize += 1;
	}
	catch (...) {
		[_bufferSwapLock unlock];	
		throw;
	}
	[_bufferSwapLock unlock];
}

- (void)resizeWithOldSuperviewSize:(NSSize)oldBoundsSize {
	[self setFrame:[[self superview] bounds]];
	[self needsDisplay];
}

- (void)keyDown:(NSEvent *)theEvent {
	if ([theEvent keyCode] == 53){
		if ([self isInFullScreenMode]) {
			[self exitFullScreenModeWithOptions:nil];
		}
	}
}

- (void) startCountdown {
}

- (void) displayCountdown:(unsigned)count {
}

- (void) finishCountdown {
}

- (void) startDrawing {
}

- (void) stopDrawing {
}

- (const vector<const InstrumentState*>*) acquireLatestStates {
	/* swap buffers */
	[_bufferSwapLock lock];
	if (_drawBuffer == _stateBuffer1) {
		_drawBuffer = _stateBuffer2;
		_loadBuffer = _stateBuffer1;
	}
	else {
		_drawBuffer = _stateBuffer1;
		_loadBuffer = _stateBuffer2;
		
	}
	
	_drawBufferSize = _loadBufferSize; //assume previous draw buffer is complete
	_loadBufferSize = 0;
	[_bufferSwapLock unlock];
	
	/* prepare return buffer */
	_returnBuffer->resize(_drawBufferSize, NULL);
	copy(_drawBuffer->begin(), 
		 _drawBuffer->begin() + _drawBufferSize,
		 _returnBuffer->begin());
	return _returnBuffer;
}

@end
